# lexer.py

TT_KEYWORD = 'KEYWORD'
TT_IDENTIFIER = 'IDENTIFIER'
TT_CONST = 'CONST'
TT_OPERATOR = 'OPERATOR'
TT_DELIMITER = 'DELIMITER'
TT_EOF = 'EOF'

# 关键字映射表（修复了 'FROM' 错误）
KEYWORDS = {
    'SELECT': 'SELECT',
    'FROM': 'FROM',      # 原来写成了 'WHERE'，已修复
    'WHERE': 'WHERE',
    'CREATE': 'CREATE',
    'TABLE': 'TABLE',
    'INSERT': 'INSERT',
    'INTO': 'INTO',
    'VALUES': 'VALUES',
    'DELETE': 'DELETE',
}

class Token:
    def __init__(self, type_, value=None, pos_start=None, pos_end=None):
        self.type = type_
        self.value = value
        self.pos_start = pos_start
        self.pos_end = pos_end

    def matches(self, type_, value):
        return self.type == type_ and self.value == value

    def __repr__(self):
        if self.value is not None:
            return f'{self.type}:{self.value}'
        return f'{self.type}'


class Position:
    def __init__(self, idx, ln, col, fn, ftxt):
        self.idx = idx
        self.ln = ln
        self.col = col
        self.fn = fn
        self.ftxt = ftxt

    def advance(self, current_char=None):
        self.idx += 1
        self.col += 1
        if current_char == '\n':
            self.ln += 1
            self.col = 0
        return self

    def copy(self):
        return Position(self.idx, self.ln, self.col, self.fn, self.ftxt)


class Error:
    def __init__(self, pos_start, pos_end, error_name, details):
        self.pos_start = pos_start
        self.pos_end = pos_end
        self.error_name = error_name
        self.details = details
    
    def as_string(self):
        result = f'{self.error_name}: {self.details}\n'
        result += f'File {self.pos_start.fn}, line {self.pos_start.ln + 1}'
        return result


class IllegalCharError(Error):
    def __init__(self, pos_start, pos_end, details):
        super().__init__(pos_start, pos_end, 'Illegal Character', details)


# 字符集定义
DIGITS = '0123456789'
LETTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
LETTERS_DIGITS = LETTERS + DIGITS


class Lexer:
    def __init__(self, fn, text):
        self.fn = fn
        self.text = text
        self.pos = Position(-1, 0, -1, fn, text)  # 正确传入 ftxt=text
        self.current_char = None
        self.advance()

    def advance(self):
        self.pos.advance(self.current_char)
        self.current_char = self.text[self.pos.idx] if self.pos.idx < len(self.text) else None

    def make_tokens(self):
        tokens = []

        while self.current_char is not None:
            if self.current_char in ' \t':
                # 跳过空格和制表符
                self.advance()
            elif self.current_char in ';\n(),':
                # 处理分隔符：分号、换行、左括号、右括号、逗号
                tokens.append(Token(TT_DELIMITER, self.current_char, self.pos.copy(), self.pos.copy()))
                self.advance()
            elif self.current_char in DIGITS:
                tokens.append(self.make_number())
            elif self.current_char in LETTERS:
                tokens.append(self.make_identifier())
            elif self.current_char == "'":
                tokens.append(self.make_string())
            elif self.current_char in '+-*/<>=':
                # 处理操作符（包括 >=, <=, != 等，但当前只支持简单组合）
                op = self.current_char
                self.advance()
                if self.current_char == '=':
                    op += '='
                    self.advance()
                tokens.append(Token(TT_OPERATOR, op))
            else:
                # 遇到无法识别的字符，报错
                pos_start = self.pos.copy()
                char = self.current_char
                self.advance()
                return [], IllegalCharError(pos_start, self.pos, f"'{char}'")

        # 添加结束标记
        tokens.append(Token(TT_EOF, pos_start=self.pos))
        return tokens, None

    def make_number(self):
        num_str = ''
        dot_count = 0
        pos_start = self.pos.copy()

        while self.current_char is not None and (self.current_char in DIGITS or self.current_char == '.'):
            if self.current_char == '.':
                if dot_count == 1:
                    break
                dot_count += 1
                num_str += '.'
            else:
                num_str += self.current_char
            self.advance()

        if dot_count == 0:
            return Token(TT_CONST, int(num_str), pos_start, self.pos)
        else:
            return Token(TT_CONST, float(num_str), pos_start, self.pos)

    def make_identifier(self):
        id_str = ''
        pos_start = self.pos.copy()

        while self.current_char is not None and self.current_char in LETTERS_DIGITS + '_':
            id_str += self.current_char
            self.advance()

        tok_type = TT_KEYWORD if id_str.upper() in KEYWORDS else TT_IDENTIFIER
        return Token(tok_type, id_str, pos_start, self.pos)

    def make_string(self):
        string = ''
        pos_start = self.pos.copy()
        self.advance()  # 跳过开头的 '

        while self.current_char is not None and self.current_char != "'":
            string += self.current_char
            self.advance()

        if self.current_char == "'":
            self.advance()  # 跳过结尾的 '
        return Token(TT_CONST, string, pos_start, self.pos)